package com.huan.groovy;

import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyCodeSource;
import org.codehaus.groovy.runtime.EncodingGroovyMethods;

import java.lang.reflect.Method;
import java.security.PrivilegedAction;

/**
 * java通过GroovyClassLoader动态加载类
 * <a href="https://groovy-lang.org/integrating.html">集成文档</a>
 *
 * @author huan.fu
 * @date 2024/7/15 - 23:01
 */
public class GroovyClassLoaderTest {

    public static void main(String[] args) throws Exception {
        GroovyClassLoader loader = new GroovyClassLoader();
        String text = "class Foo {\n" +
                "    \n" +
                "    private byte[] a = new byte[102400000]\n" +
                "    \n" +
                "    def doIt(){\n" +
                "        byte[] ab = new byte[1024000]\n" +
                "        println \"ok\"\n" +
                "    }\n" +
                "    \n" +
                "}\n";
        String fileName = "Script_" + EncodingGroovyMethods.md5(text) + ".groovy";
        GroovyCodeSource gcs = createCodeSource((PrivilegedAction<GroovyCodeSource>) () -> new GroovyCodeSource(text, fileName, "/groovy/script"));
        // 此处需要给true,否则会有内存泄漏
        gcs.setCachable(true);
        Class aClass = loader.parseClass(gcs);

        Thread.sleep(30000);

        for (int i = 0; i < 1000000000; i++) {
            GroovyCodeSource gcs1 = createCodeSource((PrivilegedAction<GroovyCodeSource>) () -> new GroovyCodeSource(text, fileName, "/groovy/script"));
            gcs1.setCachable(true);
            Class aClass1 = loader.parseClass(gcs1);

            System.out.println(aClass);
            System.out.println(aClass1);
            System.out.println(aClass == aClass1);
            Object instance = aClass1.newInstance();
            Method method = aClass1.getMethod("doIt");
            System.out.println(method.invoke(instance));
            System.out.println("===============");
        }

    }

    private static GroovyCodeSource createCodeSource(PrivilegedAction<GroovyCodeSource> action) {
        return java.security.AccessController.doPrivileged(action);
    }
}
